#!/bin/bash

# 多人贪吃蛇游戏服务器健康检查脚本
# 用于监控服务器状态和自动重启

# 配置变量
SERVER_URL="http://localhost:13000"
PID_FILE="/var/run/snake-game.pid"
LOG_FILE="./logs/health-check.log"
MAX_RETRIES=3
RETRY_INTERVAL=5
TIMEOUT=10

# 颜色输出
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# 日志函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1" | tee -a "$LOG_FILE"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1" | tee -a "$LOG_FILE"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1" | tee -a "$LOG_FILE"
}

# 创建日志目录
mkdir -p "$(dirname "$LOG_FILE")"

# 检查服务器是否响应
check_server_response() {
    local url=$1
    local timeout=$2
    
    if curl -f -s --max-time "$timeout" "$url" > /dev/null 2>&1; then
        return 0
    else
        return 1
    fi
}

# 检查进程是否运行
check_process() {
    if [ -f "$PID_FILE" ]; then
        local pid=$(cat "$PID_FILE")
        if ps -p "$pid" > /dev/null 2>&1; then
            return 0
        else
            log_warning "PID file exists but process $pid is not running"
            rm -f "$PID_FILE"
            return 1
        fi
    else
        # 尝试通过进程名查找
        if pgrep -f "node.*server.js" > /dev/null; then
            return 0
        else
            return 1
        fi
    fi
}

# 检查端口是否被占用
check_port() {
    local port=${1:-3000}
    if netstat -tuln | grep ":$port " > /dev/null 2>&1; then
        return 0
    else
        return 1
    fi
}

# 获取服务器状态信息
get_server_stats() {
    local response
    response=$(curl -s --max-time 5 "$SERVER_URL/api/stats" 2>/dev/null)
    
    if [ $? -eq 0 ] && [ -n "$response" ]; then
        echo "Server Stats: $response"
    else
        echo "Unable to fetch server statistics"
    fi
}

# 重启服务器
restart_server() {
    log "Attempting to restart server..."
    
    # 尝试优雅停止
    if [ -f "$PID_FILE" ]; then
        local pid=$(cat "$PID_FILE")
        log "Sending SIGTERM to process $pid"
        kill -TERM "$pid" 2>/dev/null
        
        # 等待进程结束
        local count=0
        while [ $count -lt 10 ] && ps -p "$pid" > /dev/null 2>&1; do
            sleep 1
            count=$((count + 1))
        done
        
        # 如果进程仍在运行，强制终止
        if ps -p "$pid" > /dev/null 2>&1; then
            log_warning "Process $pid did not terminate gracefully, sending SIGKILL"
            kill -KILL "$pid" 2>/dev/null
        fi
        
        rm -f "$PID_FILE"
    fi
    
    # 终止所有相关进程
    pkill -f "node.*server.js" 2>/dev/null
    
    # 等待端口释放
    local count=0
    while [ $count -lt 10 ] && check_port 3000; do
        sleep 1
        count=$((count + 1))
    done
    
    # 启动服务器
    if [ -f "./start.sh" ]; then
        log "Starting server using start.sh"
        ./start.sh start
    elif command -v pm2 > /dev/null; then
        log "Starting server using PM2"
        pm2 start ecosystem.config.js --env production
    else
        log "Starting server directly"
        nohup node server.js > ./logs/server.log 2>&1 &
        echo $! > "$PID_FILE"
    fi
    
    # 等待服务器启动
    sleep 5
}

# 发送通知（可扩展）
send_notification() {
    local message=$1
    local level=${2:-info}
    
    # 这里可以添加邮件、Slack、微信等通知方式
    log "NOTIFICATION [$level]: $message"
    
    # 示例：发送邮件（需要配置 sendmail）
    # echo "$message" | mail -s "Snake Game Server Alert" admin@example.com
    
    # 示例：发送到 Slack（需要配置 webhook）
    # curl -X POST -H 'Content-type: application/json' \
    #      --data "{\"text\":\"$message\"}" \
    #      YOUR_SLACK_WEBHOOK_URL
}

# 主健康检查函数
health_check() {
    local retry_count=0
    local check_passed=false
    
    log "Starting health check..."
    
    # 检查进程是否运行
    if ! check_process; then
        log_error "Server process is not running"
        send_notification "Snake Game Server process is not running" "error"
        restart_server
        return 1
    fi
    
    # 检查端口是否监听
    if ! check_port 3000; then
        log_error "Server is not listening on port 3000"
        send_notification "Snake Game Server is not listening on port 3000" "error"
        restart_server
        return 1
    fi
    
    # 检查服务器响应
    while [ $retry_count -lt $MAX_RETRIES ]; do
        if check_server_response "$SERVER_URL" "$TIMEOUT"; then
            check_passed=true
            break
        else
            retry_count=$((retry_count + 1))
            log_warning "Health check failed (attempt $retry_count/$MAX_RETRIES)"
            
            if [ $retry_count -lt $MAX_RETRIES ]; then
                sleep $RETRY_INTERVAL
            fi
        fi
    done
    
    if [ "$check_passed" = true ]; then
        log_success "Health check passed"
        get_server_stats
        return 0
    else
        log_error "Health check failed after $MAX_RETRIES attempts"
        send_notification "Snake Game Server health check failed after $MAX_RETRIES attempts" "critical"
        restart_server
        return 1
    fi
}

# 显示帮助信息
show_help() {
    echo "Snake Game Server Health Check Script"
    echo ""
    echo "Usage: $0 [OPTIONS]"
    echo ""
    echo "Options:"
    echo "  -h, --help          Show this help message"
    echo "  -c, --check         Run health check once"
    echo "  -m, --monitor       Run continuous monitoring"
    echo "  -r, --restart       Force restart server"
    echo "  -s, --stats         Show server statistics"
    echo "  -t, --test          Test notification system"
    echo "  --url URL           Set server URL (default: $SERVER_URL)"
    echo "  --timeout SECONDS   Set timeout (default: $TIMEOUT)"
    echo "  --retries COUNT     Set max retries (default: $MAX_RETRIES)"
    echo ""
    echo "Examples:"
    echo "  $0 -c                    # Run single health check"
    echo "  $0 -m                    # Start continuous monitoring"
    echo "  $0 --url http://localhost:3001 -c  # Check different URL"
    echo ""
}

# 连续监控模式
monitor_mode() {
    local interval=${1:-60}  # 默认每60秒检查一次
    
    log "Starting continuous monitoring (interval: ${interval}s)"
    send_notification "Snake Game Server monitoring started" "info"
    
    while true; do
        health_check
        sleep "$interval"
    done
}

# 解析命令行参数
while [[ $# -gt 0 ]]; do
    case $1 in
        -h|--help)
            show_help
            exit 0
            ;;
        -c|--check)
            health_check
            exit $?
            ;;
        -m|--monitor)
            monitor_mode "${2:-60}"
            exit 0
            ;;
        -r|--restart)
            restart_server
            exit 0
            ;;
        -s|--stats)
            get_server_stats
            exit 0
            ;;
        -t|--test)
            send_notification "Test notification from Snake Game Server" "test"
            exit 0
            ;;
        --url)
            SERVER_URL="$2"
            shift
            ;;
        --timeout)
            TIMEOUT="$2"
            shift
            ;;
        --retries)
            MAX_RETRIES="$2"
            shift
            ;;
        *)
            echo "Unknown option: $1"
            show_help
            exit 1
            ;;
    esac
    shift
done

# 如果没有参数，运行单次健康检查
if [ $# -eq 0 ]; then
    health_check
    exit $?
fi